#include "VSDx9Renderer.h"
#include "VS2DTexSampler.h"
#include "VSGeometry.h"
#include "VSString.h"
#include "VSResourceManager.h"
#include "VSShaderStringFactory.h"
#include "VSDirectionLight.h"
#include "VSPointLight.h"
#include "VSSpotLight.h"
#include "VSGraphicInclude.h"
using namespace VSEngine2;

void VSDX9Renderer::SetMaterialVShaderConstant(MaterialShaderPara1 &MSPara1,unsigned int uiPassType,VSVShader *pVShader)
{
	if (uiPassType == VSPass::PT_MATERIAL)
	{
		VSMatrix3X3W WorldViewProjectMat;
		VSTransform World = MSPara1.pGeometry->GetWorldTransform();
		WorldViewProjectMat = World.GetCombine()* MSPara1.pCamera->GetViewMatrix() * MSPara1.pCamera->GetProjMatrix();
		VSMatrix3X3W  * TempMatrix  = (VSMatrix3X3W  *)pVShader->m_pUserConstant[0]->GetDate();
		*TempMatrix = WorldViewProjectMat;

		VSVertexBuffer * pVBuffer = MSPara1.pGeometry->GetMeshDate()->GetVertexBuffer();
		if(MSPara1.pGeometry->GetAffectBoneNum() && pVBuffer->GetBlendWeightDate() && pVBuffer->GetBlendIndicesDate())
		{
			VSVector3W  * TempVector  = (VSVector3W  *)pVShader->m_pUserConstant[1]->GetDate();
			VSArray<VSVector3W> & Buffer = MSPara1.pGeometry->GetSkinWeightBuffer();
			VSMemcpy(TempVector, Buffer.GetBuffer(),Buffer.GetNum() * sizeof(VSVector3W));		

		}
	}
	else if (uiPassType == VSPass::PT_NORMALDEPTH || uiPassType == VSPass::PT_PREZ)
	{
		VSMatrix3X3W WorldViewProjectMat;
		VSMatrix3X3W WorldViewMat;

		VSTransform World = MSPara1.pGeometry->GetWorldTransform();

		WorldViewMat = World.GetCombine()* MSPara1.pCamera->GetViewMatrix();
		WorldViewProjectMat = WorldViewMat * MSPara1.pCamera->GetProjMatrix();

		VSMatrix3X3W  * TempMatrix  = (VSMatrix3X3W  *)pVShader->m_pUserConstant[0]->GetDate();
		*TempMatrix = WorldViewProjectMat;


		TempMatrix  = (VSMatrix3X3W  *)pVShader->m_pUserConstant[1]->GetDate();
		*TempMatrix = WorldViewMat;

		VSVertexBuffer * pVBuffer = MSPara1.pGeometry->GetMeshDate()->GetVertexBuffer();
		if(MSPara1.pGeometry->GetAffectBoneNum() && pVBuffer->GetBlendWeightDate() && pVBuffer->GetBlendIndicesDate())
		{
			VSVector3W  * TempVector  = (VSVector3W  *)pVShader->m_pUserConstant[2]->GetDate();
			VSArray<VSVector3W> & Buffer = MSPara1.pGeometry->GetSkinWeightBuffer();
			VSMemcpy(TempVector, Buffer.GetBuffer(),Buffer.GetNum() * sizeof(VSVector3W));		

		}

		

	}


}

void VSDX9Renderer::SetMaterialPShaderConstant(MaterialShaderPara1 &MSPara1,unsigned int uiPassType,VSPShader *pPShader)
{
	if (uiPassType == VSPass::PT_MATERIAL)
	{
		if (!MSPara1.LightArray.GetNum() ||!MSPara1.LightArray.GetNum())
		{
			MSPara1.pMaterialInstance->SetPShaderValue(pPShader);
		}
		else
		{
			VSArray<VSLightPtr> & LightArray = MSPara1.LightArray;
			VSTransform World = MSPara1.pGeometry->GetWorldTransform();
			VSMatrix3X3W  *TempMatrix  = (VSMatrix3X3W  *)pPShader->m_pUserConstant[0]->GetDate();
			*TempMatrix = World.GetCombine();

			VSVector3 * pCameraPos = (VSVector3 *) pPShader->m_pUserConstant[1]->GetDate();
			*pCameraPos= MSPara1.pCamera->GetWorldTranslate();

			int iLightNum[VSLight::LT_MAX] = { 0 };	
			VSVector3W * pLightBuffer[VSLight::LT_MAX] = { NULL };
			for (unsigned int i = 0 ; i < LightArray.GetNum() ; i++)
			{
				if (LightArray[i])
				{
					for (unsigned int j = 0 ; j < VSLight::LT_MAX ; j++)
					{
						if (LightArray[i]->GetLightType() == j)
						{

							iLightNum[j]++;
						}
					}
				}
			}
			unsigned int uiIndex = 2;
			for(unsigned int i = 0 ; i < VSLight::LT_MAX ; i++)
			{
				if (!iLightNum[i])
				{
					continue;
				}
				pLightBuffer[i] = (VSVector3W *) pPShader->m_pUserConstant[uiIndex]->GetDate();
				uiIndex++;
			}
			for (unsigned int i = 0 ; i < LightArray.GetNum() ; i++)
			{
				if (LightArray[i])
				{
					VSLight* pLight = LightArray[i];
					if (LightArray[i]->GetLightType() == VSLight::LT_DIRECTION)
					{
						
						*pLightBuffer[VSLight::LT_DIRECTION] = ((VSDirectionLight *)pLight)->m_Diffuse;
						pLightBuffer[VSLight::LT_DIRECTION]++;
						*pLightBuffer[VSLight::LT_DIRECTION] = ((VSDirectionLight *)pLight)->m_Specular;
						pLightBuffer[VSLight::LT_DIRECTION]++;
						const VSMatrix3X3 &Rotator = ((VSDirectionLight *)pLight)->GetWorldRotate();
						VSVector3 U,V,N;
						Rotator.GetUVN(U,V,N);

						pLightBuffer[VSLight::LT_DIRECTION]->x = N.x;
						pLightBuffer[VSLight::LT_DIRECTION]->y = N.y;
						pLightBuffer[VSLight::LT_DIRECTION]->z = N.z;
						pLightBuffer[VSLight::LT_DIRECTION]++;
					}
					else if (LightArray[i]->GetLightType() == VSLight::LT_POINT)
					{
						*pLightBuffer[VSLight::LT_POINT] = ((VSPointLight *)pLight)->m_Diffuse;
						pLightBuffer[VSLight::LT_POINT]++;
						*pLightBuffer[VSLight::LT_POINT] = ((VSPointLight *)pLight)->m_Specular;
						pLightBuffer[VSLight::LT_POINT]++;
						pLightBuffer[VSLight::LT_POINT]->x = ((VSPointLight *)pLight)->GetWorldTranslate().x;
						pLightBuffer[VSLight::LT_POINT]->y = ((VSPointLight *)pLight)->GetWorldTranslate().y;
						pLightBuffer[VSLight::LT_POINT]->z = ((VSPointLight *)pLight)->GetWorldTranslate().z;
						pLightBuffer[VSLight::LT_POINT]++;
						pLightBuffer[VSLight::LT_POINT]->x = ((VSPointLight *)pLight)->m_Attenuation0;
						pLightBuffer[VSLight::LT_POINT]->y = ((VSPointLight *)pLight)->m_Attenuation1;
						pLightBuffer[VSLight::LT_POINT]->z = ((VSPointLight *)pLight)->m_Attenuation2;
						pLightBuffer[VSLight::LT_POINT]++;
					}
					else if (LightArray[i]->GetLightType() == VSLight::LT_SPOT)
					{
						*pLightBuffer[VSLight::LT_SPOT] = ((VSSpotLight *)pLight)->m_Diffuse;
						pLightBuffer[VSLight::LT_SPOT]++;
						*pLightBuffer[VSLight::LT_SPOT] = ((VSSpotLight *)pLight)->m_Specular;
						pLightBuffer[VSLight::LT_SPOT]++;
						pLightBuffer[VSLight::LT_SPOT]->x = ((VSSpotLight *)pLight)->GetWorldTranslate().x;
						pLightBuffer[VSLight::LT_SPOT]->y = ((VSSpotLight *)pLight)->GetWorldTranslate().y;
						pLightBuffer[VSLight::LT_SPOT]->z = ((VSSpotLight *)pLight)->GetWorldTranslate().z;
						pLightBuffer[VSLight::LT_SPOT]++;
						const VSMatrix3X3 &Rotator = ((VSSpotLight *)pLight)->GetWorldRotate();
						VSVector3 U,V,N;
						Rotator.GetUVN(U,V,N);
						pLightBuffer[VSLight::LT_SPOT]->x = N.x;
						pLightBuffer[VSLight::LT_SPOT]->y = N.y;
						pLightBuffer[VSLight::LT_SPOT]->z = N.z;
						pLightBuffer[VSLight::LT_SPOT]++;
						pLightBuffer[VSLight::LT_SPOT]->x = ((VSSpotLight *)pLight)->m_Attenuation0;
						pLightBuffer[VSLight::LT_SPOT]->y = ((VSSpotLight *)pLight)->m_Attenuation1;
						pLightBuffer[VSLight::LT_SPOT]->z = ((VSSpotLight *)pLight)->m_Attenuation2;
						pLightBuffer[VSLight::LT_SPOT]++;
						pLightBuffer[VSLight::LT_SPOT]->x = ((VSSpotLight *)pLight)->m_Falloff;
						pLightBuffer[VSLight::LT_SPOT]->y = ((VSSpotLight *)pLight)->m_Theta;
						pLightBuffer[VSLight::LT_SPOT]->z = ((VSSpotLight *)pLight)->m_Phi;
						pLightBuffer[VSLight::LT_SPOT]++;
					}
				}
			}
			MSPara1.pMaterialInstance->SetPShaderValue(pPShader);
		}
	}
	else if (uiPassType == VSPass::PT_NORMALDEPTH)
	{
		VSTransform World = MSPara1.pGeometry->GetWorldTransform();
		VSMatrix3X3W  *TempMatrix  = (VSMatrix3X3W  *)pPShader->m_pUserConstant[0]->GetDate();
		*TempMatrix = World.GetCombine();

		float  * Temp  = (float *)pPShader->m_pUserConstant[1]->GetDate();
		*Temp = MSPara1.pCamera->GetZFar();	
		MSPara1.pMaterialInstance->SetPShaderValue(pPShader);
	}
	else if (uiPassType == VSPass::PT_PREZ)
	{
		float  * Temp  = (float *)pPShader->m_pUserConstant[0]->GetDate();
		*Temp = MSPara1.pCamera->GetZFar();	
	}
	
}
